package example.hellosecurity.config;

import example.hellosecurity.filter.JwtAuthenticationFilter;
import example.hellosecurity.handler.CustomAccessDeniedHandler;
import example.hellosecurity.handler.CustomAuthenticationEntryPoint;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * @author ：FuXx
 * @className : example.hellosecurity.config.SecurityConfog
 * @since ：2024/8/19
 */
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    private final SecurityIgnore securityIgnore;

    public SecurityConfig(SecurityIgnore securityIgnore) {
        this.securityIgnore = securityIgnore;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        return http.csrf(AbstractHttpConfigurer::disable)
                .logout(AbstractHttpConfigurer::disable)
                .httpBasic(AbstractHttpConfigurer::disable)
                .formLogin(AbstractHttpConfigurer::disable)
                .anonymous(AbstractHttpConfigurer::disable)
                .rememberMe(AbstractHttpConfigurer::disable)
                .addFilterBefore(new JwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
                .sessionManagement((configurer) -> configurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .authorizeHttpRequests((registry) -> {
                    // 设置白名单
                    registry.requestMatchers(this.securityIgnore.getIgnores()).permitAll()
                            // 允许预检请求
                            .requestMatchers(HttpMethod.OPTIONS).permitAll()
                            // 其他请求都需要认证
                            .anyRequest().authenticated();
                })
                .exceptionHandling((configurer) -> {
                    configurer.authenticationEntryPoint(new CustomAuthenticationEntryPoint());
                    configurer.accessDeniedHandler(new CustomAccessDeniedHandler());
                })
                .build();
    }
}
